package org.jeecg.modules.xindian.reconciliation.controller;

import cn.hutool.core.date.DateUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.xindian.reconciliation.controller.req.ReportReq;
import org.jeecg.modules.xindian.reconciliation.dto.rsp.ChannelReportInfo;
import org.jeecg.modules.xindian.reconciliation.dto.rsp.InComeReportInfo;
import org.jeecg.modules.xindian.reconciliation.dto.rsp.SalesmanReportInfo;
import org.jeecg.modules.xindian.reconciliation.mapper.PolicySettlementStatisticsMapper;
import org.jeecg.modules.xindian.reconciliation.service.impl.PolicySettlementTypeStatisticsServiceImpl;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Api(tags = "业务报表统计")
@RestController
@RequestMapping("/banck/businessReport")
@Slf4j
public class BusinessReportController {
    @Autowired
    private PolicySettlementStatisticsMapper policySettlementStatisticsMapper;
    @Autowired
    private ISysBaseAPI iSysBaseAPI;

    /**
     * 渠道报表
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "渠道报表", notes = "渠道报表")
    @PostMapping(value = "/channelReport")
    public Result<List<ChannelReportInfo>> channelReport(@RequestBody ReportReq req) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<ChannelReportInfo> channelReportInfos = policySettlementStatisticsMapper.queryChannelReportInfo(date,req.getCompany());
        processChannel(channelReportInfos);
        updateChannelDict(channelReportInfos,"DZQY");
        return Result.ok(channelReportInfos);
    }


    /**
     * 渠道报表
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "渠道报表Excel导出", notes = "渠道报表Excel导出")
    @GetMapping(value = "/channelReportExcel")
    public ModelAndView channelReportExcel(ReportReq req,HttpServletRequest request) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<ChannelReportInfo> channelReportInfos = policySettlementStatisticsMapper.queryChannelReportInfo(date,req.getCompany());;
        processChannel(channelReportInfos);
        updateChannelDict(channelReportInfos,"DZQY");
        return this.exportXls(request, channelReportInfos, ChannelReportInfo.class, "渠道");
    }


    /**
     * 导出excel
     *
     * @param request
     */
    protected <T> ModelAndView exportXls(HttpServletRequest request, List<T> exportList, Class<T> clazz, String title) {
        // Step.1 组装查询条件
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // Step.3 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        //此处设置的filename无效 ,前端会重更新设置一下
        mv.addObject(NormalExcelConstants.FILE_NAME, title);
        mv.addObject(NormalExcelConstants.CLASS, clazz);
        //update-begin--Author:liusq  Date:20210126 for：图片导出报错，ImageBasePath未设置--------------------
        ExportParams exportParams = new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title);
        exportParams.setType(ExcelType.HSSF);
        mv.addObject(NormalExcelConstants.PARAMS, exportParams);
        mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
        return mv;
    }

    /**
     * 渠道报表
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "业务员报表", notes = "业务员报表")
    @PostMapping(value = "/salespersonReport")
    public Result<List<SalesmanReportInfo>> salespersonReport(@RequestBody ReportReq req) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<SalesmanReportInfo> salesmanReportInfos = policySettlementStatisticsMapper.querySalemanReportInfo(date,req.getCompany());;
        processSalesman(salesmanReportInfos);
        updateSalesDict(salesmanReportInfos,"DZQY");
        return Result.ok(salesmanReportInfos);
    }


    /**
     * 渠道报表
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "业务员报表", notes = "业务员报表")
    @PostMapping(value = "/naturalTrafficReport")
    public Result<List<SalesmanReportInfo>> naturalTrafficReport(@RequestBody ReportReq req) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<SalesmanReportInfo> salesmanReportInfos = policySettlementStatisticsMapper.queryNaturalTrafficReport(date,req.getCompany());;
        processSalesman(salesmanReportInfos);
        updateSalesDict(salesmanReportInfos,"DZQY");
        return Result.ok(salesmanReportInfos);
    }

    /**
     * 业务员报表Excel导出
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "业务员报表Excel导出", notes = "业务员报表Excel导出")
    @GetMapping(value = "/salespersonReportExcel")
    public ModelAndView salespersonReportExcel(ReportReq req,HttpServletRequest request) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<SalesmanReportInfo> salesmanReportInfos = policySettlementStatisticsMapper.querySalemanReportInfo(date,req.getCompany());;
        processSalesman(salesmanReportInfos);
        updateSalesDict(salesmanReportInfos,"DZQY");
        return this.exportXls(request, salesmanReportInfos, SalesmanReportInfo.class, "业务员");
    }
    /**
     * 业务员报表Excel导出
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "业务员报表Excel导出", notes = "业务员报表Excel导出")
    @GetMapping(value = "/naturalTrafficReportExcel")
    public ModelAndView naturalTrafficReportExcel(ReportReq req,HttpServletRequest request) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<SalesmanReportInfo> salesmanReportInfos = policySettlementStatisticsMapper.queryNaturalTrafficReport(date,req.getCompany());;
        updateSalesDict(salesmanReportInfos,"DZQY");
        return this.exportXls(request, salesmanReportInfos, SalesmanReportInfo.class, "自然流量");
    }

    private void updateSalesDict(List<SalesmanReportInfo> statics, String dictCode){
        List<DictModel>  dictModels =  iSysBaseAPI.getDictItems(dictCode);
        Map<String,DictModel> modelMap = dictModels.stream().collect(Collectors.toMap(DictModel::getValue, Function.identity()));
        statics.forEach(commonDataStatic -> {
            DictModel tagModel =  modelMap.get(commonDataStatic.getArea());
            String tag = tagModel==null?commonDataStatic.getArea():tagModel.getText();
            commonDataStatic.setArea(tag);
        });
    }
    private void updateIncomeDict(List<InComeReportInfo> statics, String dictCode){
        List<DictModel>  dictModels =  iSysBaseAPI.getDictItems(dictCode);
        Map<String,DictModel> modelMap = dictModels.stream().collect(Collectors.toMap(DictModel::getValue, Function.identity()));
        statics.forEach(commonDataStatic -> {
            DictModel tagModel =  modelMap.get(commonDataStatic.getArea());
            String tag = tagModel==null?commonDataStatic.getArea():tagModel.getText();
            commonDataStatic.setArea(tag);
        });
    }
    private void updateChannelDict(List<ChannelReportInfo> statics, String dictCode){
        List<DictModel>  dictModels =  iSysBaseAPI.getDictItems(dictCode);
        Map<String,DictModel> modelMap = dictModels.stream().collect(Collectors.toMap(DictModel::getValue, Function.identity()));
        statics.forEach(commonDataStatic -> {
            DictModel tagModel =  modelMap.get(commonDataStatic.getArea());
            String tag = tagModel==null?commonDataStatic.getArea():tagModel.getText();
            commonDataStatic.setArea(tag);
        });
    }
    /**
     * 利润报表
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "利润报表", notes = "利润报表")
    @PostMapping(value = "/incomeStatementReport")
    public Result<List<InComeReportInfo>> incomeStatementReport(@RequestBody ReportReq req) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<InComeReportInfo> inComeReportInfos = policySettlementStatisticsMapper.queryInsuranceReportInfo(date,req.getCompany());;
        processIncome(inComeReportInfos);
        updateIncomeDict(inComeReportInfos,"DZQY");
        return Result.ok(inComeReportInfos);
    }


    /**
     * 业务员报表Excel导出
     *
     * @return
     */
    //@AutoLog(value = "杭州银行资金流水-分页列表查询")
    @ApiOperation(value = "利润报表Excel导出", notes = "利润报表Excel导出")
    @GetMapping(value = "/incomeStatementReportExcel")
    public ModelAndView incomeStatementReportExcel(ReportReq req,HttpServletRequest request) {
        Assert.hasText(req.getDate(), "账单周期不能为空");
        String date = DateUtil.format(DateUtil.parseDate(req.getDate()),"yyyy-MM");
        List<InComeReportInfo> inComeReportInfos = policySettlementStatisticsMapper.queryInsuranceReportInfo(date,req.getCompany());;
        processIncome(inComeReportInfos);
        updateIncomeDict(inComeReportInfos,"DZQY");
        return this.exportXls(request, inComeReportInfos, InComeReportInfo.class, "利润");
    }

    protected void processChannel(List<ChannelReportInfo> channelReportInfos) {
        channelReportInfos.forEach(channelReportInfo -> {
            BigDecimal income = channelReportInfo.getInsuranceFee().multiply(BigDecimal.valueOf(0.97)).divide(PolicySettlementTypeStatisticsServiceImpl.PREMIUM_TAX_POINT, RoundingMode.CEILING)
                    .subtract(channelReportInfo.getChannelFee()).subtract(channelReportInfo.getChannelAloneFee())
                    .subtract(channelReportInfo.getSystemFee());
            channelReportInfo.setIncome(income);
            if(channelReportInfo.getExTaxPremium().compareTo(BigDecimal.ZERO)!=0){
                channelReportInfo.setIncomeRate(income.divide(channelReportInfo.getExTaxPremium(),4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
            }
        });
    }

    protected void processSalesman(List<SalesmanReportInfo> salesmanReportInfos) {
        salesmanReportInfos.forEach(salesmanReportInfo->{
            BigDecimal income = salesmanReportInfo.getInsuranceFee().multiply(BigDecimal.valueOf(0.97)).divide(PolicySettlementTypeStatisticsServiceImpl.PREMIUM_TAX_POINT, RoundingMode.CEILING)
                    .subtract(salesmanReportInfo.getSalesmanFee())
                    .subtract(salesmanReportInfo.getSystemFee());
            salesmanReportInfo.setIncome(income);
            salesmanReportInfo.setIncomeRate(income.divide(salesmanReportInfo.getExTaxPremium(),4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
        });
    }

    protected void processIncome(List<InComeReportInfo> incomeStatementReport) {
        incomeStatementReport.forEach(salesmanReportInfo->{
            BigDecimal income = salesmanReportInfo.getInsuranceFee().multiply(BigDecimal.valueOf(0.97)).divide(PolicySettlementTypeStatisticsServiceImpl.PREMIUM_TAX_POINT, RoundingMode.CEILING).setScale(2, RoundingMode.HALF_UP)
                    .subtract(salesmanReportInfo.getChannelFee()).subtract(salesmanReportInfo.getSalesmanFee())
                    .subtract(salesmanReportInfo.getSystemFee());
            salesmanReportInfo.setIncome(income);
            salesmanReportInfo.setIncomeRate(income.divide(salesmanReportInfo.getExTaxPremium(),4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
        });
    }
}
